﻿/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Windows Forms Controls Class Library
 * Version 2.00
 * 
 * Toolbox Entry Control Class
 *      Provides a UI element for a selectable item within a section of a toolbox control.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;

namespace Adaptive.Foundation.Windows.Forms
{
    /// <summary>
    /// Provides a UI element for a selectable item within a section of a toolbox control.
    /// </summary>
    public partial class ToolboxEntryControl : ToolboxControlBase
    {
        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// Foreground brush instance.
        /// </summary>
        private SolidBrush _foreBrush;
        /// <summary>
        /// Background brush instance.
        /// </summary>
        private SolidBrush _backBrush;
        /// <summary>
        /// Border pen instance.
        /// </summary>
        private Pen _borderPen;
        /// <summary>
        /// Rectangle for drawing a border.
        /// </summary>
        private Rectangle _borderRectangle;
        /// <summary>
        /// Flag indicating whether the mouse is over the control.
        /// </summary>
        private bool _mouseOver;
        /// <summary>
        /// Contains a reference pointer to an object being represented.
        /// </summary>
        private object _reference;
        /// <summary>
        /// Indicates the type of object being represented.
        /// </summary>
        private SupportedToolboxTypes _currentType = SupportedToolboxTypes.NotSupported;
        /// <summary>
        /// Text to be displayed.
        /// </summary>
        private string _text = string.Empty;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public ToolboxEntryControl()
            : base()
        {
            InitializeComponent();

            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.ContainerControl, false);
            SetStyle(ControlStyles.Opaque, false);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.Selectable, false);
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            SetStyle(ControlStyles.UserPaint, true);

            RecreateBrushes();
        }
        /// <summary>
        /// Deallocates internally allocated objects.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                ClearBrushes();
                if (components != null)
                    components.Dispose();
            }

            _reference = null;
            _foreBrush = null;
            _backBrush = null;
            _borderPen = null;
            components = null;
            base.Dispose(disposing);
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets or sets the reference to an object to be represented in a toolbox.
        /// </summary>
        /// <value>
        /// A string or other object with a name value.
        /// </value>
        public object ReferenceData
        {
            get { return _reference; }
            set
            {
                _reference = value;
                _currentType = GetSupportType();
                SetText();
            }
        }
        /// <summary>
        /// Gets or sets the text of the control.
        /// </summary>
        /// <value>
        /// The text associated with this control.
        /// </value>
        /// <remarks>
        /// Setting this property explicitly will remove any reference to any object
        /// other than the supplied string.
        /// </remarks>
        [Browsable(true), DefaultValue(""), Description("Text to be displayed."),
         DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override string Text
        {
            get
            {
                SetText();
                return _text;
            }
            set
            {
                if (value != _text)
                {
                    _text = value;
                    _currentType = SupportedToolboxTypes.String;
                    _reference = value;
                    Invalidate();
                }
            }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Protected Methods / Event Methods
         *------------------------------------------------------------------------------*/
        #region Protected Methods / Event Methods
        /// <summary>
        /// Initializes the content of the control before the event handlers are assigned.
        /// </summary>
        protected override void InitializeContent()
        {
            _borderRectangle = new Rectangle(0, 0, Width - 1, Height - 1);
        }
        /// <summary>
        /// Clears the brushes used for drawing.
        /// </summary>
        protected override void ClearBrushes()
        {
            if (_foreBrush != null)
                _foreBrush.Dispose();
            if (_backBrush != null)
                _backBrush.Dispose();
            if (_borderPen != null)
                _borderPen.Dispose();

            _foreBrush = null;
            _borderPen = null;
            _borderPen = null;
        }
        /// <summary>
        /// Recreates the brushes used for drawing.
        /// </summary>
        protected override void RecreateBrushes()
        {
            if (_mouseOver)
            {
                _backBrush = new SolidBrush(ItemHighlightBackColor);
                _foreBrush = new SolidBrush(ItemHighlightForeColor);
                _borderPen = new Pen(ItemBorderColor);
            }
            else
            {
                _backBrush = new SolidBrush(ItemBackColor);
                _foreBrush = new SolidBrush(ItemForeColor);
                _borderPen = null;
            }
        }
        /// <summary>
        /// Forces the control to re-draw when the colors are changed.
        /// </summary>
        protected override void ResetColors()
        {
            ClearBrushes();
            RecreateBrushes();
            base.ResetColors(); 
        }
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.MouseEnter"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
        protected override void OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);
            _mouseOver = true;
            ResetColors();
        }
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.MouseLeave"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            _mouseOver = false;
            ResetColors();
        }
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.MouseDown"/> event and begins a drag-and-drop operation.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
                OnRightClick(EventArgs.Empty);
            else
            {
                base.OnMouseDown(e);
                DoDragDrop(this, DragDropEffects.All);
            }
        }
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.Resize"/> event and resets the border rectangle.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            _borderRectangle = new Rectangle(0, 0, Width - 1, Height - 1);
        }
        /// <summary>
        /// Paints the background of the control.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data.</param>
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            base.OnPaintBackground(e);

            //Draw the background.
            e.Graphics.FillRectangle(_backBrush, ClientRectangle);

            //Draw the border.
            if (_borderPen != null)
                e.Graphics.DrawRectangle(_borderPen, _borderRectangle);
        }
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.Paint"/> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data.</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            //Basic control paint.
            base.OnPaint(e);

            //Set for anti-aliasing.
            if (AntiAlias)
                e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

            //Draw the text.
            e.Graphics.DrawString(Text, Font, _foreBrush, new Point(2 + TextIndentation, 0));
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Private Methods / Functions
        /// <summary>
        /// Sets the value returned by the text property.
        /// </summary>
        /// <remarks>
        /// This determines which property is read to get the display value for the item.
        /// </remarks>
        private void SetText()
        {
            if (_reference != null)
            {
                switch (_currentType)
                {
                    case SupportedToolboxTypes.String:
                        _text = (string)_reference;
                        break;

                    case SupportedToolboxTypes.INamedInstance:
                        _text = ((INamedInstance)_reference).Name;
                        break;

                    case SupportedToolboxTypes.NamedDisposableObjectBase:
                        _text = ((NamedDisposableObjectBase)_reference).Name;
                        break;

                    case SupportedToolboxTypes.Control:
                        _text = ((Control)_reference).Text;
                        if (_text.Length == 0)
                            _text = ((Control)_reference).Name;
                        break;

                    default:
                        _text = string.Empty;
                        break;
                }
            }
        }
        /// <summary>
        /// Determines the type of the related data object.
        /// </summary>
        /// <returns>
        /// A <see cref="SupportedToolboxTypes"/> enumerated value.
        /// </returns>
        private SupportedToolboxTypes GetSupportType()
        {
            SupportedToolboxTypes returnValue = SupportedToolboxTypes.NotSupported;

            if (_reference is string)
            {
                returnValue = SupportedToolboxTypes.String;
            }
            else if (_reference is System.Windows.Forms.Control)
            {
                returnValue = SupportedToolboxTypes.Control;
            }
            else if (_reference is Adaptive.Foundation.INamedInstance)
            {
                returnValue = SupportedToolboxTypes.INamedInstance;
            }
            else if (_reference is Adaptive.Foundation.NamedDisposableObjectBase)
            {
                returnValue = SupportedToolboxTypes.NamedDisposableObjectBase;
            }
            return returnValue;
        }
        #endregion
    }
}